#include "rtp/NackGenerator.h"
#include <iostream>
#include "deplibUV.h"

namespace Rtp {
    static constexpr size_t MaxPacketAge { 10000u };
    static constexpr size_t MaxNackPackets { 1000u };
    static constexpr uint32_t DefaultRtt { 100u };
    static constexpr uint8_t MaxNackRetries { 10u };
    static constexpr uint64_t TimerInterval { 40u };

    NackGenerator::NackGenerator(Listener *listener, unsigned int sendNackDelayMs): listener(listener), 
    sendNackDelayMs(sendNackDelayMs), timer(new TimerHandle(this)), rtt(DefaultRtt) {}

    NackGenerator::~NackGenerator() {
        delete this->timer;
    }

    //return  true 该包是之前请求过重传的包 false 该包不是重传包
    bool NackGenerator::ReceivePacket(Rtp::RtpPacket *packet, bool isRecovered) {

        const uint16_t seq = packet->GetSequenceNumber();
        const bool isKeyFrame = packet->IsKeyFrame();

        if (!this->started) {
            this->started = true;
            this->lastSeq = seq;

            if (isKeyFrame) {
                this->keyFrameList.insert(seq);
            }
            // 表示该包不是之前请求过的重传包
            return false;
        }

        if (seq == this->lastSeq) { // 序列号和上一包的序列号相同
            return false;
        }
 
        if (SeqManager<uint16_t>::IsSeqLowerThan(seq, this->lastSeq)) {   // IsSeqLowerThan 处理序列号回绕的问题
            // 检查该包是否在NACK列表中(即之前被判定为丢失的包)
            auto it = this->nackList.find(seq);
            // 如果是NACK列表中的包
            if (it != this->nackList.end()) {
                std::cout << "Nacked packet received [ssrc:" << packet->GetSsrc() << "seq:" << packet->GetSequenceNumber() 
                << "recovered" <<  (isRecovered ? "true" : "false") << std::endl;

                auto retries = it->second.retries;

                this->nackList.erase(it); // 从NACK列表中删除

                return retries != 0;   // 如果重传次数不为0，说明是之前请求过的重传包，返回true
            }
            // 如果不是NACK列表中的包且未标记为已恢复
            if (!isRecovered) {
                std::cout << "ignoring older packet not present in the NACK list:" << packet->GetSsrc() << "seq:" << packet->GetSequenceNumber() << std::endl; 
            }
            // 忽略不在NACK列表中的旧包
            return false;
        }

        if (isKeyFrame) {
            this->keyFrameList.insert(seq);
        }
        // 清理过期的关键帧记录
        {   
            // upper_bound(k) 返回第一个键​​大于​​k的元素
            // lower_bound(k) 返回第一个键​​不小于​​k的元素（即大于或等于k的第一个元素） 返回的是一个迭代器
            auto it = this->keyFrameList.lower_bound(seq - MaxPacketAge); // lower_bound() 用于在有序关联容器中查找第一个不小于给定键的元素

            if (it != this->keyFrameList.begin()) {
                this->keyFrameList.erase(this->keyFrameList.begin(), it);
            }
        }

        // 恢复包的特殊处理
        if (isRecovered) {
            this->recoveredList.insert(seq);
            // 清理过期的恢复包记录
            auto it = this->recoveredList.lower_bound(seq - MaxPacketAge);

            if (it != this->recoveredList.begin()) {
                this->recoveredList.erase(this->recoveredList.begin(), it);
            }
             // 通过RTX重传收到的包不触发NACK处理
            return false;
        }

        // 核心丢包检测逻辑
        AddPacketsToNackList(this->lastSeq + 1, seq);

        this->lastSeq = seq;

        // 立即触发 NACK 请求
        const std::vector<uint16_t> nackBatch = GetNackBatch(NackFilter::SEQ);

        if (!nackBatch.empty()) {
            this->listener->OnNackGeneratorNackRequired(nackBatch);
        }

        if (!this->timer->IsActive()) {
            MayRunTimer();
        }

        return false;
    }

    void NackGenerator::AddPacketsToNackList(uint16_t seqStart, uint16_t seqEnd) {
        // MaxPacketAge === 通过滑动窗口机制 在内存效率、丢包检测精度和序列号回绕兼容性之间取得平衡
        auto it = this->nackList.lower_bound(seqEnd - MaxPacketAge); // 这是一个范围控制
        this->nackList.erase(this->nackList.begin(), it); // 清空至it的位置  [begin(), it) 前闭后开

        const uint16_t numNewNack = seqEnd - seqStart;

        if (static_cast<uint16_t>(this->nackList.size()) + numNewNack > MaxNackPackets) {
            while (RemoveNackItemsUntilKeyFrame() && static_cast<uint16_t>(this->nackList.size()) + numNewNack > MaxNackPackets) {
            }

            if (static_cast<uint16_t>(this->nackList.size()) + numNewNack > MaxNackPackets) {
                std::cout << "NACK list full, clearing it and requesting a key frame [seqEnd:" << seqEnd << std::endl;

                this->nackList.clear();
                this->listener->OnNackGeneratorKeyFrameRequired();
                return;
            }
        }

        for (uint16_t seq = seqStart; seq != seqEnd; ++seq) {
            auto it = this->nackList.find(seq);
            if (it != this->nackList.end()) {
                throw std::runtime_error("packet already in the NACK list");
            }

            // Do not send NACK for packets that are already recovered by RTX.
            if (this->recoveredList.find(seq) != this->recoveredList.end()) {
                continue;
            }

            this->nackList.emplace(std::make_pair(seq, NackInfo{DepLibUV::GetTimeMs(), seq, seq}));
        }
    }

    bool NackGenerator::RemoveNackItemsUntilKeyFrame() {
        while (!this->keyFrameList.empty()) {
            auto it = this->nackList.lower_bound(*this->keyFrameList.begin());

            if (it != this->nackList.begin()) {
                this->nackList.erase(this->nackList.begin(), it);
                return true;
            }

            this->keyFrameList.erase(this->keyFrameList.begin());
        }
        return false;
    }

    std::vector<uint16_t> NackGenerator::GetNackBatch(NackFilter filter) {
        const uint64_t nowMs = DepLibUV::GetTimeMs();
        std::vector<uint16_t> nackBatch;

        auto it = this->nackList.begin();

        while (it != this->nackList.end()) {
            
            NackInfo& nackInfo = it->second;

            const uint16_t seq = nackInfo.seq;

            if (this->sendNackDelayMs > 0 && nowMs - nackInfo.createdAtMs < this->sendNackDelayMs) {
                ++it;
                continue;
            }

            if (filter == NackFilter::SEQ && nackInfo.sendAtMs == 0 && (
                nackInfo.sendAtSeq == this->lastSeq || SeqManager<uint16_t>::IsSeqHigherThan(this->lastSeq, nackInfo.sendAtSeq)
            )) {
                nackBatch.emplace_back(seq);
                nackInfo.retries++;
                nackInfo.sendAtMs = nowMs;

                if (nackInfo.retries >= MaxNackPackets) {
                    std::cout << "sequence number removed from the NACK list due to max retries:" << seq << std::endl;
                    it = this->nackList.erase(it);
                } else {
                    ++it;
                }
                continue;
            }

            if (filter == NackFilter::TIME && (nackInfo.sendAtMs == 0 || nowMs - nackInfo.sendAtMs >= (this->rtt > 0u ? this->rtt : DefaultRtt))) {
                nackBatch.emplace_back(seq);
                nackInfo.retries ++;
                nackInfo.sendAtMs = nowMs;

                if (nackInfo.retries >= MaxNackRetries) {
                    std::cout << "sequence number removed from the NACK list due to max retries [filter:time, seq" << seq << std::endl;
                    it = this->nackList.erase(it);
                } else {
                    ++it;
                }
                continue;
            }

            ++it;
        }

        return nackBatch;
    }

    void NackGenerator::Reset() {
        this->nackList.clear();
        this->keyFrameList.clear();

        this->recoveredList.clear();

        this->started = false;
        this->lastSeq = 0u;
    }

    inline void NackGenerator::MayRunTimer() const {
        if (this->nackList.empty()) {
            this->timer->Stop();
        } else {
            this->timer->Start(TimerInterval);
        }
    }

    inline void NackGenerator::OnTimer(TimerHandle */**timer */) {
        const std::vector<uint16_t> nackBatch = GetNackBatch(NackFilter::TIME);
        if (!nackBatch.empty()) {
            this->listener->OnNackGeneratorNackRequired(nackBatch);
        }
        MayRunTimer();
    }
}